home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 726-750 / 741 / rkrm_lib1 / rkrm_lib1.lha / Intuition / Boopsi / RKMButClass.c next >
C/C++ Source or Header  |  1992-09-03  |  21KB  |  503 lines

  1. ;/* RKMButClass.c - Example Boopsi gadget for RKRM:Libraries
  2. ; Execute me to compile me with Lattice 5.10b
  3. LC -b1 -d0 -cfistq -v -y -j73 RKMButClass.c
  4. Blink FROM LIB:c.o,RKMButClass.o TO TestBut LIBRARY LIB:LC.lib,LIB:Amiga.lib
  5. quit
  6. */
  7. /*
  8. Copyright (c) 1992 Commodore-Amiga, Inc.
  9.  
  10. This example is provided in electronic form by Commodore-Amiga, Inc. for
  11. use with the "Amiga ROM Kernel Reference Manual: Libraries", 3rd Edition,
  12. published by Addison-Wesley (ISBN 0-201-56774-1).
  13.  
  14. The "Amiga ROM Kernel Reference Manual: Libraries" contains additional
  15. information on the correct usage of the techniques and operating system
  16. functions presented in these examples.  The source and executable code
  17. of these examples may only be distributed in free electronic form, via
  18. bulletin board or as part of a fully non-commercial and freely
  19. redistributable diskette.  Both the source and executable code (including
  20. comments) must be included, without modification, in any copy.  This
  21. example may not be published in printed form or distributed with any
  22. commercial product.  However, the programming techniques and support
  23. routines set forth in these examples may be used in the development
  24. of original executable software products for Commodore Amiga computers.
  25.  
  26. All other rights reserved.
  27.  
  28. This example is provided "as-is" and is subject to change; no
  29. warranties are made.  All use is at your own risk. No liability or
  30. responsibility is assumed.
  31. */
  32.  
  33.  
  34. #include <exec/types.h>
  35. #include <intuition/intuition.h>
  36. #include <intuition/classes.h>
  37. #include <intuition/classusr.h>
  38. #include <intuition/imageclass.h>
  39. #include <intuition/gadgetclass.h>
  40. #include <intuition/cghooks.h>
  41. #include <intuition/icclass.h>
  42. #include <utility/tagitem.h>
  43. #include <utility/hooks.h>
  44. #include <clib/exec_protos.h>
  45. #include <clib/intuition_protos.h>
  46. #include <clib/graphics_protos.h>
  47. #include <clib/utility_protos.h>
  48. #include <clib/alib_protos.h>
  49. #include <clib/alib_stdio_protos.h>
  50.  
  51. #include <graphics/gfxmacros.h>
  52.  
  53. #ifdef LATTICE
  54. int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
  55. int chkabort(void) { return(0); }
  56. #endif
  57.  
  58. UBYTE *vers = "\0$VER: TestBut 37.1";
  59.  
  60. /***********************************************************/
  61. /****************      Class specifics      ****************/
  62. /***********************************************************/
  63. #define RKMBUT_Pulse   (TAG_USER + 1)
  64.  
  65. struct ButINST
  66. {
  67.     LONG midX, midY; /* Coordinates of middle of gadget */
  68. };
  69.  
  70. /* ButINST has one flag:  */
  71. #define ERASE_ONLY   0x00000001 /* Tells rendering routine to */
  72.                                 /* only erase the gadget, not */
  73.                                 /* rerender a new one.  This  */
  74.                                 /* lets the gadget erase it-  */
  75.                                 /* self before it rescales.   */
  76.  
  77. /* The functions in this module */
  78. Class *initRKMButGadClass(void);
  79. BOOL   freeRKMButGadClass(Class *);
  80. ULONG  dispatchRKMButGad(Class *, Object *, Msg);
  81. void   NotifyPulse(Class *, Object *, ULONG, LONG, struct gpInput *);
  82. ULONG  RenderRKMBut(Class *, struct Gadget *, struct gpRender *);
  83. void   geta4(void);
  84. void   MainLoop(ULONG, ULONG);
  85.  
  86. /*************************************************************************************************/
  87. /* The main() function connects an RKMButClass object to a Boopsi integer gadget, which displays */
  88. /* the RKMButClass gadget's RKMBUT_Pulse value.  The code scales and move the gadget while it is */
  89. /* in place.                                                                                     */
  90. /*************************************************************************************************/
  91.  
  92. struct TagItem pulse2int[] =
  93. {
  94.     {RKMBUT_Pulse, STRINGA_LongVal},
  95.     {TAG_END,}
  96. };
  97.  
  98. #define INTWIDTH  40
  99. #define INTHEIGHT 20
  100.  
  101. struct Library *IntuitionBase, *UtilityBase, *GfxBase;
  102. struct Window *w;
  103. Class *rkmbutcl;
  104. struct Gadget *integer, *but;
  105. struct IntuiMessage *msg;
  106.  
  107. void main(void)
  108. {
  109.     if (IntuitionBase = OpenLibrary("intuition.library", 37L))
  110.     {
  111.         if (UtilityBase = OpenLibrary("utility.library", 37L))
  112.         {
  113.             if (GfxBase = OpenLibrary("graphics.library", 37L))
  114.             {
  115.                 if (w = OpenWindowTags(NULL,
  116.                     WA_Flags,       WFLG_DEPTHGADGET | WFLG_DRAGBAR |
  117.                                         WFLG_CLOSEGADGET | WFLG_SIZEGADGET,
  118.                     WA_IDCMP,       IDCMP_CLOSEWINDOW,
  119.                     WA_Width,           640,
  120.                     WA_Height,          200,
  121.                     TAG_END))
  122.                 {
  123.                     WindowLimits(w, 450, 200, 640, 200);
  124.  
  125.                     if (rkmbutcl = initRKMButGadClass())
  126.                     {
  127.                         if (integer = (struct Gadget *)NewObject(NULL,
  128.                                        "strgclass",
  129.                                        GA_ID,            1L,
  130.                                        GA_Top,           (w->BorderTop) + 5L,
  131.                                        GA_Left,          (w->BorderLeft) + 5L,
  132.                                        GA_Width,         INTWIDTH,
  133.                                        GA_Height,        INTHEIGHT,
  134.                                        STRINGA_LongVal,  0L,
  135.                                        STRINGA_MaxChars, 5L,
  136.                                        TAG_END))
  137.                         {
  138.                             if (but = (struct Gadget *)NewObject(rkmbutcl,
  139.                                        NULL,
  140.                                        GA_ID,       2L,
  141.                                        GA_Top,      (w->BorderTop) + 5L,
  142.                                        GA_Left,     integer->LeftEdge +
  143.                                                         integer->Width + 5L,
  144.                                        GA_Width,    40L,
  145.                                        GA_Height,   INTHEIGHT,
  146.                                        GA_Previous, integer,
  147.                                        ICA_MAP,     pulse2int,
  148.                                        ICA_TARGET,  integer,
  149.                                        TAG_END))
  150.                             {
  151.                                 AddGList(w, integer, -1, -1, NULL);
  152.                                 RefreshGList(integer, w, NULL, -1);
  153.  
  154.                                 SetWindowTitles(w,
  155.                                     "<-- Click to resize gadget Height",
  156.                                     NULL);
  157.                                 MainLoop(TAG_DONE, 0L);
  158.  
  159.                                 SetWindowTitles(w,
  160.                                     "<-- Click to resize gadget Width",
  161.                                     NULL);
  162.                                 MainLoop(GA_Height, 100L);
  163.  
  164.                                 SetWindowTitles(w,
  165.                                     "<-- Click to resize gadget Y position",
  166.                                     NULL);
  167.                                 MainLoop(GA_Width, 100L);
  168.  
  169.                                 SetWindowTitles(w,
  170.                                     "<-- Click to resize gadget X position",
  171.                                     NULL);
  172.                                 MainLoop(GA_Top, but->TopEdge + 20);
  173.  
  174.                                 SetWindowTitles(w,
  175.                                     "<-- Click to quit", NULL);
  176.                                 MainLoop(GA_Left, but->LeftEdge + 20);
  177.  
  178.                                 RemoveGList(w, integer, -1);
  179.                                 DisposeObject(but);
  180.                             }
  181.                             DisposeObject(integer);
  182.                         }
  183.                         freeRKMButGadClass(rkmbutcl);
  184.                     }
  185.                     CloseWindow(w);
  186.                 }
  187.                 CloseLibrary(GfxBase);
  188.             }
  189.             CloseLibrary(UtilityBase);
  190.         }
  191.         CloseLibrary(IntuitionBase);
  192.     }
  193. }
  194.  
  195. void MainLoop(ULONG attr, ULONG value)
  196. {
  197.     ULONG done = FALSE;
  198.  
  199.     SetGadgetAttrs(but, w, NULL, attr, value, TAG_DONE);
  200.  
  201.     while (done == FALSE)
  202.     {
  203.         WaitPort((struct MsgPort *)w->UserPort);
  204.         while (msg = (struct IntuiMessage *)
  205.            GetMsg((struct MsgPort *)w->UserPort))
  206.         {
  207.             if (msg->Class == IDCMP_CLOSEWINDOW)
  208.             {
  209.                 done = TRUE;
  210.             }
  211.             ReplyMsg(msg);
  212.         }
  213.     }
  214. }
  215.  
  216. /***********************************************************/
  217. /**    Make the class and set up the dispatcher's hook    **/
  218. /***********************************************************/
  219. Class   *initRKMButGadClass(void)
  220. {
  221.     Class *cl = NULL;
  222.     extern ULONG HookEntry();     /* defined in amiga.lib */
  223.  
  224.     if ( cl =  MakeClass( NULL,
  225.                 "gadgetclass", NULL,
  226.                 sizeof ( struct ButINST ),
  227.                 0 ))
  228.     {
  229.         /* initialize the cl_Dispatcher Hook    */
  230.         cl->cl_Dispatcher.h_Entry = HookEntry;
  231.         cl->cl_Dispatcher.h_SubEntry = dispatchRKMButGad;
  232.     }
  233.     return ( cl );
  234. }
  235.  
  236. /***********************************************************/
  237. /******************     Free the class      ****************/
  238. /***********************************************************/
  239. BOOL freeRKMButGadClass( Class *cl )
  240. {
  241.     return (FreeClass(cl));
  242. }
  243.  
  244. /***********************************************************/
  245. /**********       The RKMBut class dispatcher      *********/
  246. /***********************************************************/
  247. ULONG dispatchRKMButGad(Class *cl, Object *o, Msg msg)
  248. {
  249.     struct ButINST *inst;
  250.     ULONG retval = FALSE;
  251.     Object *object;
  252.  
  253.     /* SAS/C and Manx function to make sure register A4
  254.        contains a pointer to global data */
  255.     geta4();
  256.  
  257.     switch (msg->MethodID)
  258.     {
  259.         case OM_NEW:       /* First, pass up to superclass */
  260.             if (object = (Object *)DoSuperMethodA(cl, o, msg))
  261.             {
  262.                 struct Gadget *g = (struct Gadget *)object;
  263.  
  264.                             /* Initial local instance data */
  265.                 inst = INST_DATA(cl, object);
  266.                 inst->midX   = g->LeftEdge + ( (g->Width) / 2);
  267.                 inst->midY   = g->TopEdge + ( (g->Height) / 2);
  268.  
  269.                 retval = (ULONG)object;
  270.             }
  271.             break;
  272.         case GM_HITTEST:
  273.                    /* Since this is a rectangular gadget this  */
  274.                    /* method always returns GMR_GADGETHIT.     */
  275.             retval = GMR_GADGETHIT;
  276.             break;
  277.         case GM_GOACTIVE:
  278.             inst = INST_DATA(cl, o);
  279.  
  280.                     /* Only become active if the GM_GOACTIVE   */
  281.                     /* was triggered by direct user input.     */
  282.             if (((struct gpInput *)msg)->gpi_IEvent)
  283.             {
  284.                        /* This gadget is now active, change    */
  285.                        /* visual state to selected and render. */
  286.                 ((struct Gadget *)o)->Flags |= GFLG_SELECTED;
  287.                                 RenderRKMBut(cl, (struct Gadget *)o, (struct gpRender *)msg);
  288.                 retval = GMR_MEACTIVE;
  289.             }
  290.             else            /* The GM_GOACTIVE was not         */
  291.                             /* triggered by direct user input. */
  292.                 retval = GMR_NOREUSE;
  293.             break;
  294.         case GM_RENDER:
  295.             retval = RenderRKMBut(cl, (struct Gadget *)o, (struct gpRender *)msg);
  296.             break;
  297.         case GM_HANDLEINPUT:   /* While it is active, this gadget sends its superclass an        */
  298.                                /* OM_NOTIFY pulse for every IECLASS_TIMER event that goes by     */
  299.                                /* (about one every 10th of a second).  Any object that is        */
  300.                                /* connected to this gadget will get A LOT of OM_UPDATE messages. */
  301.             {
  302.                 struct Gadget *g = (struct Gadget *)o;
  303.                 struct gpInput *gpi = (struct gpInput *)msg;
  304.                 struct InputEvent *ie = gpi->gpi_IEvent;
  305.  
  306.                 inst = INST_DATA(cl, o);
  307.  
  308.                 retval = GMR_MEACTIVE;
  309.  
  310.                 if (ie->ie_Class == IECLASS_RAWMOUSE)
  311.                 {
  312.                     switch (ie->ie_Code)
  313.                     {
  314.                         case SELECTUP: /* The user let go of the gadget so return GMR_NOREUSE    */
  315.                                        /* to deactivate and to tell Intuition not to reuse       */
  316.                                        /* this Input Event as we have already processed it.      */
  317.  
  318.                                        /*If the user let go of the gadget while the mouse was    */
  319.                                        /*over it, mask GMR_VERIFY into the return value so       */
  320.                                        /*Intuition will send a Release Verify (GADGETUP).        */
  321.                             if ( ((gpi->gpi_Mouse).X < g->LeftEdge) ||
  322.                                  ((gpi->gpi_Mouse).X > g->LeftEdge + g->Width) ||
  323.                                  ((gpi->gpi_Mouse).Y < g->TopEdge) ||
  324.                                  ((gpi->gpi_Mouse).Y > g->TopEdge + g->Height) )
  325.                                 retval = GMR_NOREUSE | GMR_VERIFY;
  326.                             else
  327.                                 retval = GMR_NOREUSE;
  328.  
  329.                                            /* Since the gadget is going inactive, send a final   */
  330.                                            /* notification to the ICA_TARGET.                    */
  331.                             NotifyPulse(cl , o, 0L, inst->midX, (struct gp_Input *)msg);
  332.                             break;
  333.                         case MENUDOWN: /* The user hit the menu button. Go inactive and let      */
  334.                                        /* Intuition reuse the menu button event so Intuition can */
  335.                                        /* pop up the menu bar.                                   */
  336.                             retval = GMR_REUSE;
  337.  
  338.                                            /* Since the gadget is going inactive, send a final   */
  339.                                            /* notification to the ICA_TARGET.                    */
  340.                             NotifyPulse(cl , o, 0L, inst->midX, (struct gp_Input *)msg);
  341.                             break;
  342.                         default:
  343.                             retval = GMR_MEACTIVE;
  344.                     }
  345.  
  346.                 }
  347.                 else if (ie->ie_Class == IECLASS_TIMER)
  348.                               /* If the gadget gets a timer event, it sends an interim OM_NOTIFY */
  349.                     NotifyPulse(cl, o, OPUF_INTERIM, inst->midX, gpi); /*     to its superclass. */
  350.             }
  351.             break;
  352.  
  353.         case GM_GOINACTIVE:           /* Intuition said to go inactive.  Clear the GFLG_SELECTED */
  354.                                       /* bit and render using unselected imagery.                */
  355.             ((struct Gadget *)o)->Flags &= ~GFLG_SELECTED;
  356.             RenderRKMBut(cl, (struct Gadget *)o, (struct gpRender *)msg);
  357.             break;
  358.         case OM_SET:/* Although this class doesn't have settable attributes, this gadget class   */
  359.                     /* does have scaleable imagery, so it needs to find out when its size and/or */
  360.                     /* position has changed so it can erase itself, THEN scale, and rerender.    */
  361.             if ( FindTagItem(GA_Width,  ((struct opSet *)msg)->ops_AttrList) ||
  362.                  FindTagItem(GA_Height, ((struct opSet *)msg)->ops_AttrList) ||
  363.                  FindTagItem(GA_Top,    ((struct opSet *)msg)->ops_AttrList) ||
  364.                  FindTagItem(GA_Left,   ((struct opSet *)msg)->ops_AttrList) )
  365.             {
  366.                 struct RastPort *rp;
  367.                 struct Gadget *g = (struct Gadget *)o;
  368.  
  369.                 WORD x,y,w,h;
  370.  
  371.                 x = g->LeftEdge;
  372.                 y = g->TopEdge;
  373.                 w = g->Width;
  374.                 h = g->Height;
  375.  
  376.                 inst = INST_DATA(cl, o);
  377.  
  378.                 retval = DoSuperMethodA(cl, o, msg);
  379.  
  380.                                                           /* Get pointer to RastPort for gadget. */
  381.                 if (rp = ObtainGIRPort( ((struct opSet *)msg)->ops_GInfo) )
  382.                 {
  383.                                     UWORD *pens = ((struct opSet *)msg)->ops_GInfo->gi_DrInfo->dri_Pens;
  384.  
  385.                     SetAPen(rp, pens[BACKGROUNDPEN]);
  386.                     SetDrMd(rp, JAM1);                            /* Erase the old gadget.       */
  387.                     RectFill(rp, x, y, x+w, y+h);
  388.  
  389.                     inst->midX = g->LeftEdge + ( (g->Width) / 2); /* Recalculate where the       */
  390.                     inst->midY = g->TopEdge + ( (g->Height) / 2); /* center of the gadget is.    */
  391.  
  392.                                                                   /* Rerender the gadget.        */
  393.                     DoMethod(o, GM_RENDER, ((struct opSet *)msg)->ops_GInfo, rp, GREDRAW_REDRAW);
  394.                     ReleaseGIRPort(rp);
  395.                 }
  396.             }
  397.             else
  398.                 retval = DoSuperMethodA(cl, o, msg);
  399.             break;
  400.         default:          /* rkmmodelclass does not recognize the methodID, let the superclass's */
  401.                           /* dispatcher take a look at it.                                       */
  402.             retval = DoSuperMethodA(cl, o, msg);
  403.             break;
  404.     }
  405.     return(retval);
  406. }
  407.  
  408.  
  409.  
  410. /*************************************************************************************************/
  411. /************** Build an OM_NOTIFY message for RKMBUT_Pulse and send it to the superclass. *******/
  412. /*************************************************************************************************/
  413. void NotifyPulse(Class *cl, Object *o, ULONG flags, LONG mid, struct gpInput *gpi)
  414. {
  415.     struct TagItem tt[3];
  416.  
  417.     tt[0].ti_Tag = RKMBUT_Pulse;
  418.     tt[0].ti_Data = mid - ((gpi->gpi_Mouse).X + ((struct Gadget *)o)->LeftEdge);
  419.  
  420.     tt[1].ti_Tag = GA_ID;
  421.     tt[1].ti_Data = ((struct Gadget *)o)->GadgetID;
  422.  
  423.     tt[2].ti_Tag = TAG_DONE;
  424.  
  425.     DoSuperMethod(cl, o, OM_NOTIFY, tt, gpi->gpi_GInfo, flags);
  426. }
  427.  
  428.  
  429.  
  430. /*************************************************************************************************/
  431. /*******************************   Erase and rerender the gadget.   ******************************/
  432. /*************************************************************************************************/
  433. ULONG RenderRKMBut(Class *cl, struct Gadget *g, struct gpRender *msg)
  434. {
  435.     struct ButINST *inst = INST_DATA(cl, (Object *)g);
  436.     struct RastPort *rp;
  437.     ULONG retval = TRUE;
  438.     UWORD *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens;
  439.  
  440.     if (msg->MethodID == GM_RENDER)   /* If msg is truly a GM_RENDER message (not a gpInput that */
  441.                                       /* looks like a gpRender), use the rastport within it...   */
  442.         rp = msg->gpr_RPort;
  443.     else                              /* ...Otherwise, get a rastport using ObtainGIRPort().     */
  444.         rp = ObtainGIRPort(msg->gpr_GInfo);
  445.  
  446.     if (rp)
  447.     {
  448.         UWORD back, shine, shadow, w, h, x, y;
  449.  
  450.         if (g->Flags & GFLG_SELECTED) /* If the gadget is selected, reverse the meanings of the  */
  451.         {                             /* pens.                                                   */
  452.             back   = pens[FILLPEN];
  453.             shine  = pens[SHADOWPEN];
  454.             shadow = pens[SHINEPEN];
  455.         }
  456.         else
  457.         {
  458.             back   = pens[BACKGROUNDPEN];
  459.             shine  = pens[SHINEPEN];
  460.             shadow = pens[SHADOWPEN];
  461.         }
  462.         SetDrMd(rp, JAM1);
  463.  
  464.         SetAPen(rp, back);          /* Erase the old gadget.       */
  465.         RectFill(rp, g->LeftEdge,
  466.                      g->TopEdge,
  467.                      g->LeftEdge + g->Width,
  468.                      g->TopEdge + g->Height);
  469.  
  470.         SetAPen(rp, shadow);     /* Draw shadow edge.            */
  471.         Move(rp, g->LeftEdge + 1, g->TopEdge + g->Height);
  472.         Draw(rp, g->LeftEdge + g->Width, g->TopEdge + g->Height);
  473.         Draw(rp, g->LeftEdge + g->Width, g->TopEdge + 1);
  474.  
  475.         w = g->Width / 4;       /* Draw Arrows - Sorry, no frills imagery */
  476.         h = g->Height / 2;
  477.         x = g->LeftEdge + (w/2);
  478.         y = g->TopEdge + (h/2);
  479.  
  480.         Move(rp, x, inst->midY);
  481.         Draw(rp, x + w, y);
  482.         Draw(rp, x + w, y + (g->Height) - h);
  483.         Draw(rp, x, inst->midY);
  484.  
  485.         x = g->LeftEdge + (w/2) + g->Width / 2;
  486.  
  487.         Move(rp, x + w, inst->midY);
  488.         Draw(rp, x, y);
  489.         Draw(rp, x, y  + (g->Height) - h);
  490.         Draw(rp, x + w, inst->midY);
  491.  
  492.         SetAPen(rp, shine);    /* Draw shine edge.           */
  493.         Move(rp, g->LeftEdge, g->TopEdge + g->Height - 1);
  494.         Draw(rp, g->LeftEdge, g->TopEdge);
  495.         Draw(rp, g->LeftEdge + g->Width - 1, g->TopEdge);
  496.  
  497.         if (msg->MethodID != GM_RENDER) /* If we allocated a rastport, give it back.             */
  498.             ReleaseGIRPort(rp);
  499.     }
  500.     else retval = FALSE;
  501.     return(retval);
  502. }
  503.